home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Environments / PowerLisp 2.01 / Supplemental Documentation / Documentation / Appendix A. Series < prev    next >
Text File  |  1995-03-23  |  75KB  |  1,539 lines

  1. Common Lisp the Language, 2nd Edition
  2. -------------------------------------------------------------------------------
  3.  
  4. Appendix A.
  5. Series
  6.  
  7. By Richard C. Waters
  8.  
  9. [change_begin]
  10. PREFACE: A series is a data structure much like a sequence, with similar kinds
  11. of operations. The difference is that in many situations, operations on series
  12. may be composed functionally and yet execute iteratively, without the need to
  13. construct intermediate series values explicitly. In this manner, series provide
  14. both the clarity of a functional programming style and the efficiency of an
  15. iterative programming style.
  16.  
  17. The remainder of this chapter consists of a description by Richard C. Waters of
  18. his work on an existing implementation of series. This is the culmination of
  19. many years of design and use of this approach, during which some 100,000 lines
  20. of application code have been written (by about half a dozen people over the
  21. course of seven years) using the series facility in nearly all iteration
  22. situations. This includes one large system (KBEmacs) of over 40,000 lines of
  23. code.
  24.  
  25. I have edited the chapter only very lightly to conform to the overall style of
  26. this book. Please see the Preface to this book for more information about the
  27. genesis of the series approach and its relationship to the work of X3J13.
  28.  
  29.      -Guy L. Steele Jr.
  30.  
  31. [change_end]
  32. -------------------------------------------------------------------------------
  33.  
  34.    *  Introduction
  35.    *  Series Functions
  36.         o  Scanners
  37.         o  Mapping
  38.         o  Truncation and Other Simple Transducers
  39.         o  Conditional and Other Complex Transducers
  40.         o  Collectors
  41.         o  Alteration of Series
  42.    *  Optimization
  43.         o  Basic Restrictions
  44.         o  Constraint Cycles
  45.         o  Defining New Series Functions
  46.         o  Declarations
  47.    *  Primitives
  48.  
  49. -------------------------------------------------------------------------------
  50.  
  51. A.1. Introduction
  52.  
  53. [change_begin]
  54. Series combine aspects of sequences, streams, and loops. Like sequences, series
  55. represent totally ordered multi-sets. In addition, the series functions have
  56. the same flavor as the sequence functions-namely, they operate on whole series,
  57. rather than extracting elements to be processed by other functions. For
  58. instance, the series expression below computes the sum of the positive elements
  59. in a list.
  60.  
  61. (collect-sum (choose-if #'plusp (scan '(1 -2 3 -4)))) => 4
  62.  
  63. Like streams, series can represent unbounded sets of elements and are supported
  64. by lazy evaluation: each element of a series is not computed until it is
  65. needed. For instance, the series expression below returns a list of the first
  66. five even natural numbers and their sum. The call on scan-range returns a
  67. series of all the even natural numbers. However, since no elements beyond the
  68. first five are ever used, no elements beyond the first five are ever computed.
  69.  
  70. (let ((x (subseries (scan-range :from 0 :by 2) 0 5)))
  71.   (values (collect x) (collect-sum x)))
  72.   => (0 2 4 6 8) and 20
  73.  
  74. Like sequences and unlike streams, a series is not altered when its elements
  75. are accessed. For instance, both users of x above receive the same elements.
  76.  
  77. A totally ordered multi-set of elements can be represented in a loop by the
  78. successive values of a variable. This is extremely efficient, because it avoids
  79. the need to store the elements as a group in any kind of data structure. In
  80. most situations, series expressions achieve this same high level of efficiency,
  81. because they are automatically transformed into loops before being evaluated or
  82. compiled. For instance, the first expression above is transformed into a loop
  83. like the following.
  84.  
  85. (let ((sum 0))
  86.   (dolist (i '(1 -2  3 -4) sum)
  87.     (when (plusp i) (setq sum (+ sum i))))) => 4
  88.  
  89. A wide variety of algorithms can be expressed clearly and succinctly with
  90. series expressions. In particular, at least 90 percent of the loops programmers
  91. typically write can be replaced by series expressions that are much easier to
  92. understand and modify, and just as efficient. From this perspective, the key
  93. feature of series is that they are supported by a rich set of functions. These
  94. functions more or less correspond to the union of the operations provided by
  95. the sequence functions, the loop clauses, and the vector operations of APL.
  96.  
  97. Some series expressions cannot be transformed into loops. This is unfortunate,
  98. because while transformable series expressions are much more efficient than
  99. equivalent expressions involving sequences or streams, non-transformable series
  100. expressions are much less efficient. Whenever a problem comes up that blocks
  101. the transformation of a series expression, a warning message is issued. On the
  102. basis of information in the message, it is usually easy to provide an efficient
  103. fix for the problem (see section A.3).
  104.  
  105. Fortunately, most series expressions can be transformed into loops. In
  106. particular, pure expressions (ones that do not store series in variables) can
  107. always be transformed. As a result, the best approach for programmers to take
  108. is simply to write series expressions without worrying about transformability.
  109. When problems come up, they can be ignored (since they cannot lead to the
  110. computation of incorrect results) or dealt with on an individual basis.
  111.  
  112. -------------------------------------------------------------------------------
  113. Implementation note: The series functions and the theory underlying them are
  114. described in greater detail in [52,53]. These reports also discuss the
  115. algorithms required to transform series expressions into loops and explain how
  116. to obtain a portable implementation.
  117. -------------------------------------------------------------------------------
  118.  
  119. [change_end]
  120.  
  121. -------------------------------------------------------------------------------
  122.  
  123. A.2. Series Functions
  124.  
  125. [change_begin]
  126. Throughout this chapter the notation S   is used to denote the jth element of
  127. the series S. As in a list or vector, the first element of a series has the
  128. subscript zero.
  129.  
  130. The # macro character syntax #Zlist denotes a series that contains the elements
  131. of list. This syntax is also used when series are printed.
  132.  
  133. (choose-if #'symbolp #Z(a 2 b)) => #Z(a b)
  134.  
  135. Series are self-evaluating objects and the series data type is disjoint from
  136. all other types.
  137.  
  138. [Type specifier]
  139. series element-type
  140.  
  141. The type specifier (series element-type) denotes the set of series whose
  142. elements are all members of the type element-type.
  143.  
  144. [Function]
  145. series arg &rest args
  146.  
  147. The function series returns an unbounded series that endlessly repeats the
  148. values of the arguments. The second example below shows the preferred method
  149. for constructing a bounded series.
  150.  
  151. (series 'b 'c) => #Z(b c b c b c ...)
  152. (scan (list 'a 'b 'c)) => #Z(a b c)
  153.  
  154. [change_end]
  155.  
  156. -------------------------------------------------------------------------------
  157.  
  158.    *  Scanners
  159.    *  Mapping
  160.    *  Truncation and Other Simple Transducers
  161.    *  Conditional and Other Complex Transducers
  162.    *  Collectors
  163.    *  Alteration of Series
  164.  
  165. -------------------------------------------------------------------------------
  166.  
  167. A.2.1. Scanners
  168.  
  169. [change_begin]
  170. Scanners create series outputs based on non-series inputs. Either they operate
  171. based on some formula (for example, scanning a range of integers) or they
  172. enumerate the elements in an aggregate data structure (for example, scanning
  173. the elements in a list or array).
  174.  
  175. [Function]
  176. scan-range &key (:start 0) (:by 1) (:type 'number):upto :below :downto :above
  177. :length
  178.  
  179. The function scan-range returns a series of numbers starting with the :start
  180. argument (default integer 0) and counting up by the :by argument (default
  181. integer 1). The :type argument (default number) is a type specifier indicating
  182. the type of numbers in the series produced. The :type argument must be a (not
  183. necessarily proper) subtype of number. The :start and :by arguments must be of
  184. that type.
  185.  
  186. One of the last five arguments may be used to specify the kind of end test to
  187. be used; these are called termination arguments. If :upto is specified,
  188. counting continues only so long as the numbers generated are less than or equal
  189. to :upto. If :below is specified, counting continues only so long as the
  190. numbers generated are less than :below. If :downto is specified, counting
  191. continues only so long as the numbers generated are greater than or equal to
  192. :downto. If :above is specified, counting continues only so long as the numbers
  193. generated are greater than :above. If :length is specified, it must be a
  194. non-negative integer and the output series has this length.
  195.  
  196. If none of the termination arguments are specified, the output has unbounded
  197. length. If more than one termination argument is specified, it is an error.
  198.  
  199. (scan-range :upto 4) => #Z(0 1 2 3 4)
  200. (scan-range :from 1 :by -1 :above -4) => #Z(1 0 -1 -2 -3)
  201. (scan-range :from .5 :by .1 :type 'float) => #Z(.5 .6 .7 ...)
  202. (scan-range) => #Z(0 1 2 3 4 5 6 ...)
  203.  
  204. [Function]
  205. scan sequence
  206. scan type sequence
  207.  
  208. scan returns a series containing the elements of sequence in order. The type
  209. argument is a type specifier indicating the type of sequence to be scanned; it
  210. must be a (not necessarily proper) subtype of sequence. If type is omitted, it
  211. defaults to list. (This function exhibits an argument pattern that is unusual
  212. for Common Lisp: an ``optional'' argument preceding a required argument. This
  213. pattern cannot be expressed in the usual manner with &optional. It is indicated
  214. above by two definition lines, showing the two possible argument patterns.)
  215.  
  216. If the sequence is a list, it must be a proper list ending in nil. Scanning is
  217. significantly more efficient if it can be determined at compile time whether
  218. type is a subtype of list or vector and for vectors what the length of the
  219. vector is.
  220.  
  221. (scan '(a b c)) => #Z(a b c)
  222. (scan 'string "BAR") => #Z(#\B #\A #\R)
  223.  
  224. [Function]
  225. scan-sublists list
  226.  
  227. scan-sublists returns a series containing the successive sublists of list. The
  228. list must be a proper list ending in nil.
  229.  
  230. (scan-sublists '(a b c)) => #Z((a b c) (b c) (c))
  231.  
  232. [Function]
  233. scan-multiple type first-sequence &rest more-sequences
  234.  
  235. Several sequences can be scanned at once by using several calls on scan. Each
  236. call on scan will test to see when its sequence runs out of elements and
  237. execution will stop as soon as any of the sequences are exhausted. Although
  238. very robust, this approach to scanning can be inefficient. In situations where
  239. it is known in advance which sequence is the shortest, scan-multiple can be
  240. used to obtain the same results more rapidly.
  241.  
  242. scan-multiple is similar to scan except that several sequences can be scanned
  243. at once. If there are n sequence inputs, scan-multiple returns n series
  244. containing the elements of these sequences. It must be the case that none of
  245. the sequence inputs is shorter than the first sequence. All of the output
  246. series are the same length as the first input sequence. Extra elements in the
  247. other input sequences are ignored. Using scan-multiple is more efficient than
  248. using multiple instances of scan, because scan-multiple only has to check for
  249. the first input running out of elements.
  250.  
  251. If type is of the form (values    ...   ), then there must be m sequence inputs
  252. and the ith sequence must have type   . Otherwise there can be any number of
  253. sequence inputs, each of which must have type type.
  254.  
  255. (multiple-value-bind (data weights)
  256.     (scan-multiple 'list '(1 6 3 2 8) '(2 3 3 3 2))
  257.   (collect (map-fn t #'* data weights)))
  258.   => (2 18 9 6 16)
  259.  
  260. [Function]
  261. scan-lists-of-lists lists-of-lists &optional leaf-test
  262. scan-lists-of-lists-fringe lists-of-lists &optional leaf-test
  263.  
  264. The argument lists-of-lists is viewed as a tree where each internal node is a
  265. non-empty list and the elements of the list are the children of the node.
  266. scan-lists-of-lists and scan-lists-of-lists-fringe each scan lists-of-lists in
  267. preorder and return a series of its nodes. scan-lists-of-lists returns every
  268. node in the tree. scan-lists-of-lists-fringe returns only the leaf nodes.
  269.  
  270. The scan proceeds as follows. The argument lists-of-lists can be any Lisp
  271. object. If lists-of-lists is an atom or satisfies the predicate leaf-test (if
  272. present), it is a leaf node. (The predicate can count on being applied only to
  273. conses.) Otherwise, lists-of-lists is a (not necessarily proper) list. The
  274. first element of lists-of-lists is recursively scanned in full, followed by the
  275. second and so on until a non-cons cdr is encountered. Whether or not this final
  276. cdr is nil, it is ignored.
  277.  
  278. (scan-lists-of-lists '((2) (nil)))
  279.   => #Z(((2) (nil)) (2) 2 (nil) nil)
  280. (scan-lists-of-lists-fringe '((2) (nil))) => #Z(2 nil)
  281. (scan-lists-of-lists-fringe '((2) (nil))
  282.                             #'(lambda (e) (numberp (car e))))
  283.   => #Z((2) nil)
  284.  
  285. [Function]
  286. scan-alist a-list &optional (test #'eql)
  287. scan-plist plist
  288. scan-hash table
  289.  
  290. When given an association list, a property list, or a hash table
  291. (respectively), each of these functions produces two outputs: a series of keys
  292. K and a series of the corresponding values V. Each key in the input appears
  293. exactly once in the output, even if it appears more than once in the input.
  294. (The test argument of scan-alist specifies the equality test between keys; it
  295. defaults to eql.) The two outputs have the same length. Each V   is the value
  296. returned by the appropriate accessing function (cdr of assoc, getf, or gethash,
  297. respectively) when given K  . scan-alist and scan-plist scan keys in the order
  298. they appear in the underlying structure. scan-hash scans keys in no particular
  299. order.
  300.  
  301. (scan-plist '(a 1 b 3)) => #Z(a b) and #Z(1 3)
  302. (scan-alist '((a . 1) nil (a . 3) (b . 2)))
  303.   => #Z(a b) and #Z(1 2)
  304.  
  305. [Function]
  306. scan-symbols &optional (package *package*)
  307.  
  308. scan-symbols returns a series, in no particular order, and possibly containing
  309. duplicates, of the symbols accessible in package (which defaults to the current
  310. package).
  311.  
  312. [Function]
  313. scan-file file-name &optional (reader #'read)
  314.  
  315. scan-file opens the file named by the string file-name and applies the function
  316. reader to it repeatedly until the end of the file is reached. Reader must
  317. accept the standard input function arguments input-stream, eof-error-p, and
  318. eof-value as its arguments. (For instance, reader can be read,
  319. read-preserving-white-space, read-line, or read-char.) If omitted, reader
  320. defaults to read. scan-file returns a series of the values returned by reader,
  321. up to but not including the value returned when the end of the file is reached.
  322. The file is correctly closed, even if an abort occurs.
  323.  
  324. [Function]
  325. scan-fn type init step &optional test
  326.  
  327. The higher-order function scan-fn supports the general concept of scanning. The
  328. type argument is a type specifier indicating the type of values returned by
  329. init and step. The values type specifier can be used for this argument to
  330. indicate multiple types; however, type cannot indicate zero values. If type
  331. indicates m types   , then scan-fn returns m series T1, ..., Tm, where Ti has
  332. the type (series   ). The arguments init, step, and test are functions.
  333.  
  334. The init must be of type (function () (values    ...   )).
  335.  
  336. The step must be of type (function (   ...   ) (values    ...   )).
  337.  
  338. The test (if present) must be of type (function (   ...   ) t).
  339.  
  340. The elements of the Ti are computed as follows:
  341.  
  342. (values T1   ... Tm  ) = (funcall init)
  343. (values T1   ... Tm  ) = (funcall step T1   ... Tm  )
  344.  
  345. The outputs all have the same length. If there is no test, the outputs have
  346. unbounded length. If there is a test, the outputs consist of the elements up
  347. to, but not including, the first elements (with index j, say) for which the
  348. following termination test is not nil.
  349.  
  350. (funcall test T1   ... Tm  )
  351.  
  352. It is guaranteed that step will not be applied to the elements that pass this
  353. termination test.
  354.  
  355. If init, step, or test has side effects when invoked, it can count on being
  356. called in the order indicated by the equations above, with test called just
  357. before step on each cycle. However, given the lazy evaluation nature of series,
  358. these functions will not be called until their outputs are actually used (if
  359. ever). In addition, no assumptions can be made about the relative order of
  360. evaluation of these calls with regard to execution in other parts of a given
  361. series expression. The first example below scans down a list stepping two
  362. elements at a time. The second example generates two unbounded series: the
  363. integers counting up from 1 and the sequence of partial sums of the first i
  364. integers.
  365.  
  366. (scan-fn t #'(lambda () '(a b c d)) #'cddr #'null)
  367.   => #Z((a b c d) (c d))
  368.  
  369. (scan-fn '(values integer integer)
  370.          #'(lambda () (values 1 0))
  371.          #'(lambda (i sum) (values (+ i 1) (+ sum i))))
  372.   => #Z(1 2 3 4 ...) and #Z(0 1 3 6 ...)
  373.  
  374. [Function]
  375. scan-fn-inclusive type init step test
  376.  
  377. The higher-order function scan-fn-inclusive is the same as scan-fn except that
  378. the first set of elements for which test returns a non-null value is included
  379. in the output. As with scan-fn, it is guaranteed that step will not be applied
  380. to the elements for which test is non-null.
  381. [change_end]
  382.  
  383. -------------------------------------------------------------------------------
  384.  
  385. A.2.2. Mapping
  386.  
  387. [change_begin]
  388. By far the most common kind of series operation is mapping. In cognizance of
  389. this fact, four different ways are provided for specifying mapping: one
  390. fundamental form (map-fn) and three shorthand forms that are more convenient in
  391. particular common situations.
  392.  
  393. [Function]
  394. map-fn type function &rest series-inputs
  395.  
  396. The higher-order function map-fn supports the general concept of mapping. The
  397. type argument is a type specifier indicating the type of values returned by
  398. function. The values construct can be used to indicate multiple types; however,
  399. type cannot indicate zero values. If type indicates m types   , then map-fn
  400. returns m series T1, ..., Tm, where Ti has the type (series   ). The argument
  401. function is a function. The remaining arguments (if any) are all series. Let
  402. these series be S1, ..., Sn and suppose that Si has the type (series   ).
  403.  
  404. The function must be of type
  405.  
  406. (function (   ...   ) (values    ...   ))
  407.  
  408. The length of each output is the same as the length of the shortest input. If
  409. there are no bounded series inputs, the outputs are unbounded. The elements of
  410. the Ti are the results of applying function to the corresponding elements of
  411. the series inputs.
  412.  
  413. (values T1   ... Tm  ) == (funcall function S1   ... Sn  )
  414.  
  415. If function has side effects, it can count on being called first on the Si  ,
  416. then on the Si  , and so on. However, given the lazy evaluation nature of
  417. series, function will not be called on any group of input elements until the
  418. result is actually used (if ever). In addition, no assumptions can be made
  419. about the relative order of evaluation of the calls on function with regard to
  420. execution in other parts of a given series expression.
  421.  
  422. (map-fn 'integer #'+ #Z(1 2 3) #Z(4 5)) => #Z(5 7)
  423. (map-fn t #'gensym) => #Z(#:G3 #:G4 #:G5 ...)
  424. (map-fn '(values integer rational) #'floor #Z(1/4 9/5 12/3))
  425.   => #Z(0 1 4) and #Z(1/4 4/5 0)
  426.  
  427. The # macro character syntax #M makes it easy to specify uses of map-fn where
  428. type is t and the function is a named function. The notation (#Mfunction ...)
  429. is an abbreviation for (map-fn t #'function ...). The form function can be the
  430. printed representation of any Lisp object. The notation #Mfunction can appear
  431. only in the function position of a list.
  432.  
  433. (collect (#M1+ (scan '(1 2 3)))) => (2 3 4)
  434.  
  435. [Macro]
  436. mapping ({({var | ({var}*)} value)}*) {declaration}* {form}*
  437.  
  438. The macro mapping makes it easy to specify uses of map-fn where type is t and
  439. the function is a literal lambda. The syntax of mapping is analogous to that of
  440. let. The binding list specifies zero or more variables that are bound in
  441. parallel to successive values of series. The value part of each pair is an
  442. expression that must produce a series. The declarations and forms are treated
  443. as the body of a lambda expression that is mapped over the series values. A
  444. series of the first values returned by this lambda expression is returned as
  445. the result of mapping.
  446.  
  447. (mapping ((x r) (y s)) ...) ==
  448.   (map-fn t #'(lambda (x y) ...) r s)
  449. (mapping ((x (scan '(2 -2 3))))
  450.   (expt (abs x) 3))
  451.   => #Z(8 8 27)
  452.  
  453. The form mapping supports a special syntax that facilitates the use of series
  454. functions returning multiple values. Instead of being a single variable, the
  455. variable part of a var-value pair can be a list of variables. This list is
  456. treated the same way as the first argument to multiple-value-bind and can be
  457. used to access the elements of multiple series returned by a series function.
  458.  
  459. (mapping (((i v) (scan-plist '(a 1 b 2))))
  460.   (list i v))
  461.   => #Z((a 1) (b 2))
  462.  
  463. [Macro]
  464. iterate ({({var | ({var}*)} value)}*) {declaration}* {form}*
  465.  
  466. The form iterate is the same as mapping, except that after mapping the forms
  467. over the values, the results are discarded and nil is returned.
  468.  
  469. (let ((item (scan '((1) (-2) (3)))))
  470.   (iterate ((x (#Mcar item)))
  471.     (if (plusp x) (prin1 x))))
  472.   => nil (after printing ``13'')
  473.  
  474. To a first approximation, iterate and mapping differ in the same way as mapc
  475. and mapcar. In particular, like mapc, iterate is intended to be used in
  476. situations where the forms are being evaluated for side effects rather than for
  477. their results. However, given the lazy evaluation semantics of series, the
  478. difference between iterate and mapping is more than just a question of
  479. efficiency.
  480.  
  481. If mapcar is used in a situation where the output is not used, time is wasted
  482. unnecessarily creating the output list. However, if mapping is used in a
  483. situation where the output is not used, no computation is performed, because
  484. series elements are not computed until they are used. Thus iterate can be
  485. thought of as a declaration that the indicated computation is to be performed
  486. even though the output is not used for anything.
  487. [change_end]
  488.  
  489. -------------------------------------------------------------------------------
  490.  
  491. A.2.3. Truncation and Other Simple Transducers
  492.  
  493. [change_begin]
  494. Transducers compute series from series and form the heart of most series
  495. expressions. Mapping is by far the most common transducer. This section
  496. presents a number of additional simple transducers.
  497.  
  498. [Function]
  499. cotruncate &rest series-inputs
  500. until bools &rest series-inputs
  501. until-if pred &rest series-inputs
  502.  
  503. Each of these functions accepts one or more series inputs S1, ..., Sn as its
  504. &rest argument and returns n series outputs T1, ..., Tn that contain the same
  505. elements in the same order-that is, Ti  =Si  . Let k be the length of the
  506. shortest input Si. cotruncate truncates the series so that each output has
  507. length k. Let    be the position of the first element in the boolean series
  508. bools that is not nil or, if every element is nil, the length of bools. until
  509. truncates the series so that each output has length (min k   ). Let    be the
  510. position of the first element in S1 such that (pred S1  ) is not nil or, if
  511. there is no such element, the length of S1. until-if truncates the series so
  512. that each output has length (min k   ).
  513.  
  514. (cotruncate #Z(1 2 -3 4) #Z(a b c))
  515.   => #Z(1 2 -3) and #Z(a b c)
  516. (until #Z(nil nil t nil) #Z(1 2 -3 4) #Z(a b c))
  517.   => #Z(1 2) and #Z(a b)
  518. (until-if #'minusp #Z(1 2 -3 4) #Z(a b c))
  519.   => #Z(1 2) and #Z(a b)
  520.  
  521. [Function]
  522. previous items &optional (default nil) (amount 1)
  523.  
  524. The series returned by previous is the same as the input series items except
  525. that it is shifted to the right by the positive integer amount. The shifting is
  526. done by inserting amount copies of default before items and discarding amount
  527. elements from the end of items.
  528.  
  529. (previous #Z(10 11 12) 0) => #Z(0 10 11)
  530.  
  531. [Function]
  532. latch items &key :after :before :pre :post
  533.  
  534. The series returned by latch is the same as the input series items except that
  535. some of the elements are replaced by other values. latch acts like a latch
  536. electronic circuit component. Each input element causes the creation of a
  537. corresponding output element. After a specified number of non-null input
  538. elements have been encountered, the latch is triggered and the output mode is
  539. permanently changed.
  540.  
  541. The :after and :before arguments specify the latch point. The latch point is
  542. just after the :after-th non-null element in items or just before the
  543. :before-th non-null element. If neither :after nor :before is specified, an
  544. :after of 1 is assumed. If both are specified, it is an error.
  545.  
  546. If a :pre is specified, every element prior to the latch point is replaced by
  547. this value. If a :post is specified, every element after the latch point is
  548. replaced by this value. If neither is specified, a :post of nil is assumed.
  549.  
  550. (latch #Z(nil c nil d e)) => #Z(nil c nil nil nil)
  551. (latch #Z(nil c nil d e) :before 2 :post t) => #Z(nil c nil t t)
  552.  
  553. [Function]
  554. collecting-fn type init function &rest series-inputs
  555.  
  556. The higher-order function collecting-fn supports the general concept of a
  557. simple transducer with internal state. The type argument is a type specifier
  558. indicating the type of values returned by function. The values construct can be
  559. used to indicate multiple types; however, type cannot indicate zero values. If
  560. type indicates m types   , then collecting-fn returns m series T1, ..., Tm,
  561. where Ti has the type (series   ). The arguments init and function are
  562. functions. The remaining arguments (if any) are all series. Let these series be
  563. S1, ..., Sn and suppose that Si has the type (series   ).
  564.  
  565. The init must be of type (function () (values    ...   )).
  566.  
  567. The function must be of type
  568.  
  569. (function (   ...       ...   ) (values    ...   ))
  570.  
  571. The length of each output is the same as the length of the shortest input. If
  572. there are no bounded series inputs, the outputs are unbounded. The elements of
  573. the Ti are computed as follows:
  574.  
  575. (values T1   ... Tm  ) ==
  576.   (multiple-value-call function (funcall  init) S1   ... Sn  )
  577.  
  578. (values T1   ... Tm  ) ==
  579.   (funcall function T1   ... Tm   S1   ... Sn  )
  580.  
  581. If init or function has side effects, it can count on being called in the order
  582. indicated by the equations above. However, given the lazy evaluation nature of
  583. series, these functions will not be called until their outputs are actually
  584. used (if ever). In addition, no assumptions can be made about the relative
  585. order of evaluation of these calls with regard to execution in other parts of a
  586. given series expression. The second example below computes a series of partial
  587. sums of the numbers in an input series. The third example computes two output
  588. series: the partial sums of its first input and the partial products of its
  589. second input.
  590.  
  591. (defun running-averages (float-list)
  592.   (multiple-value-call #'map-fn
  593.     'float #'/
  594.     (collecting-fn '(values float integer)
  595.                    #'(lambda () (values 0.0 0)
  596.                    #'(lambda (s n x) (values (+ s x) (+ n 1))))
  597.                    float-list)))
  598.  
  599. (collecting-fn 'integer #'(lambda () 0) #'+ #Z(1 2 3))
  600.   => #Z(1 3 6)
  601.  
  602. (collecting-fn '(values integer integer)
  603.                #'(lambda () (values 0 1))
  604.                #'(lambda (sum prod x y)
  605.                    (values (+ sum x) (* prod y)))
  606.                #Z(4 6 8)
  607.                #Z(1 2 3))
  608.   => #Z(4 10 18) and #Z(1 2 6)
  609.  
  610. [change_end]
  611.  
  612. -------------------------------------------------------------------------------
  613.  
  614. A.2.4. Conditional and Other Complex Transducers
  615.  
  616. [change_begin]
  617. This section presents a number of complex transducers, including ones that
  618. support conditional computation.
  619.  
  620. [Function]
  621. choose bools &optional (items bools)
  622. choose-if pred items
  623.  
  624. Each of these functions takes in a series of elements (items) and returns a
  625. series containing the same elements in the same order, but with some elements
  626. removed. choose removes itemsj if boolsj is nil or j is beyond the end of
  627. bools. If items is omitted, choose returns the non-null elements of bools.
  628. choose-if removes itemsj if (pred itemsj) is nil.
  629.  
  630. (choose #Z(t nil t nil) #Z(a b c d)) => #Z(a c)
  631. (collect-sum (choose-if #'plusp #Z(-1 2 -3 4))) => 6
  632.  
  633. [Function]
  634. expand bools items &optional (default nil)
  635.  
  636. expand is a quasi-inverse of choose. The output contains the elements of the
  637. input series items spread out into the positions specified by the non-null
  638. elements in bools-that is, itemsj is in the position occupied by the jth
  639. non-null element in bools. The other positions in the output are occupied by
  640. default. The output stops as soon as bools runs out of elements or a non-null
  641. element in bools is encountered for which there is no corresponding element in
  642. items.
  643.  
  644. (expand #Z(nil t nil t t) #Z(a b c)) => #Z(nil a nil b c)
  645. (expand #Z(nil t nil t t) #Z(a)) => #Z(nil a nil)
  646.  
  647. [Function]
  648. split items &rest test-series-inputs
  649. split-if items &rest test-predicates
  650.  
  651. These functions are like choose and choose-if except that instead of producing
  652. one restricted output, they partition the input series items between several
  653. outputs. If there are n test inputs following items, then there are n+1
  654. outputs. Each input element is placed in exactly one output series, depending
  655. on the outcome of a sequence of tests. If the element itemsj fails the first
  656. k-1 tests and passes the kh test, it is put in the kth output. If itemsj fails
  657. every test, it is placed in the last output. In addition, all output stops as
  658. soon as any series input runs out of elements. The test inputs to split are
  659. series of values; itemsj passes the kth test if the jth element of the kth test
  660. series is not nil. The test inputs to split-if are predicates; itemsj passes
  661. the kth test if the kth test predicate returns non-null when applied to itemsj.
  662.  
  663. (split #Z(-1 2 3 -4) #Z(t nil nil t))
  664.   => #Z(-1 -4) and #Z(2 3)
  665. (multiple-value-bind (+x -x) (split-if  #Z(-1 2 3 -4) #'plusp)
  666.   (values (collect-sum +x) (collect-sum -x)))
  667.   => 5 and -5
  668.  
  669. [Function]
  670. catenate &rest series-inputs
  671.  
  672. catenate combines two or more series into one long series by appending them end
  673. to end. The length of the output is the sum of the lengths of the inputs.
  674.  
  675. (catenate #Z(b c) #Z() #Z(d)) => #Z(b c d)
  676.  
  677. [Function]
  678. subseries items start &optional below
  679.  
  680. subseries returns a series containing the elements of the input series items
  681. indexed by the non-negative integers from start up to, but not including,
  682. below. If below is omitted or greater than the length of items, the output goes
  683. all the way to the end of items.
  684.  
  685. (subseries #Z(a b c d) 1) => #Z(b c d)
  686. (subseries #Z(a b c d) 1 3) => #Z(b c)
  687.  
  688. [Function]
  689. positions bools
  690.  
  691. positions returns a series of the indices of the non-null elements in the
  692. series input bools.
  693.  
  694. (positions #Z(t nil t 44)) => #Z(0 2 3)
  695.  
  696. [Function]
  697. mask monotonic-indices
  698.  
  699. mask is a quasi-inverse of positions. The series input monotonic-indices must
  700. be a strictly increasing series of non-negative integers. The output, which is
  701. always unbounded, contains t in the positions specified by monotonic-indices
  702. and nil everywhere else.
  703.  
  704. (mask #Z(0 2 3)) => #Z(t nil t t nil nil ...)
  705. (mask #Z()) => #Z(nil nil ...)
  706. (mask (positions #Z(nil a nil b nil)))
  707.   => #Z(nil t nil t nil ...)
  708.  
  709. [Function]
  710. mingle items1 items2 comparator
  711.  
  712. The series returned by mingle contains all and only the elements of the two
  713. input series. The length of the output is the sum of the lengths of the inputs
  714. and is unbounded if either input is unbounded. The order of the elements
  715. remains unchanged; however, the elements from the two inputs are stably
  716. intermixed under the control of the comparator.
  717.  
  718. The comparator must accept two arguments and return non-null if and only if its
  719. first argument is strictly less than its second argument (in some appropriate
  720. sense). At each step, the comparator is used to compare the current elements in
  721. the two series. If the current element from items2 is strictly less than the
  722. current element from items1, the current element is removed from items2 and
  723. transferred to the output. Otherwise, the next output element comes from
  724. items1.
  725.  
  726. (mingle #Z(1 3 7 9) #Z(4 5 8) #'<) => #Z(1 3 4 5 7 8 9)
  727. (mingle #Z(1 7 3 9) #Z(4 5 8) #'<) => #Z(1 4 5 7 3 8 9)
  728.  
  729. [Function]
  730. chunk m n items
  731.  
  732. This function has the effect of breaking up the input series items into
  733. (possibly overlapping) chunks of length m. The starting positions of successive
  734. chunks differ by n. The inputs m and n must both be positive integers.
  735.  
  736. chunk produces m output series. The ith chunk provides the ith element for each
  737. of the m outputs. Suppose that the length of items is l. The length of each
  738. output is   . The ith element of the kth output is the (i*n+k)th element of
  739. items (i and k counting from zero).
  740.  
  741. Note that if l<m, there will be no output elements, and if l-m is not a
  742. multiple of n, the last few input elements will not appear in the output. If
  743. mn, one can guarantee that the last chunk will contain the last element of
  744. items by catenating
  745. n-1 copies of an appropriate padding value to the end of items.
  746.  
  747. The first example below shows chunk being used to compute a moving average. The
  748. second example shows chunk being used to convert a property list into an
  749. association list.
  750.  
  751. (mapping (((xi xi+1 xi+2) (chunk 3 1 #Z(1 5 3 4 5 6))))
  752.   (/ (+ xi xi+1 xi+2) 3))
  753.   => #Z(3 4 4 5)
  754.  
  755. (collect
  756.   (mapping (((prop val) (chunk 2 2 (scan '(a 2 b 5 c 8)))))
  757.     (cons prop val)))
  758.   => ((a . 2) (b . 5) (c . 8))
  759.  
  760. [change_end]
  761.  
  762. -------------------------------------------------------------------------------
  763.  
  764. A.2.5. Collectors
  765.  
  766. [change_begin]
  767. Collectors produce non-series outputs based on series inputs. They either
  768. create a summary value based on some formula (the sum, for example) or collect
  769. the elements of a series in an aggregate data structure (such as a list).
  770.  
  771. [Function]
  772. collect-first items &optional (default nil)
  773. collect-last items &optional (default nil)
  774. collect-nth n items &optional (default nil)
  775.  
  776. Given a series items, these functions return the first element, the last
  777. element, and the nth element, respectively. If items has no elements (or no nth
  778. element), default is returned. If default is not specified, then nil is used
  779. for default.
  780.  
  781. (collect-first #Z() 'z) => z
  782. (collect-last #Z(a b c)) => c
  783. (collect-nth 1 #Z(a b c)) => b
  784.  
  785. [Function]
  786. collect-length items
  787.  
  788. collect-length returns the number of elements in a series.
  789.  
  790. (collect-length #Z(a b c)) => 3
  791.  
  792. [Function]
  793. collect-sum numbers &optional (type 'number)
  794.  
  795. collect-sum returns the sum of the elements in a series of numbers. The type is
  796. a type specifier that indicates the type of sum to be created. If type is not
  797. specified, then number is used for the type. If there are no elements in the
  798. input, a zero (of the appropriate type) is returned.
  799.  
  800. (collect-sum #Z(1.1 1.2 1.3)) => 3.6
  801. (collect-sum #Z() 'complex) => #C(0 0)
  802.  
  803. [Function]
  804. collect-max numbers
  805. collect-min numbers
  806.  
  807. Given a series of non-complex numbers, these functions compute the maximum
  808. element and the minimum element, respectively. If there are no elements in the
  809. input, nil is returned.
  810.  
  811. (collect-max #Z(2 1 4 3)) => 4
  812. (collect-min #Z(1.2 1.1 1.4 1.3)) => 1.1
  813. (collect-min #Z()) => nil
  814.  
  815. [Function]
  816. collect-and bools
  817.  
  818. collect-and returns the and of the elements in a series. As with the macro and,
  819. nil is returned if any element of bools is nil. Otherwise, the last element of
  820. bools is returned. The value t is returned if there are no elements in bools.
  821.  
  822. (collect-and #Z(a b c)) => c
  823. (collect-and #Z(a nil c)) => nil
  824.  
  825. [Function]
  826. collect-or bools
  827.  
  828. collect-or returns the or of the elements in a series. As with the macro or,
  829. nil is returned if every element of bools is nil. Otherwise, the first non-null
  830. element of bools is returned. The value nil is returned if there are no
  831. elements in bools.
  832.  
  833. (collect-or #Z(nil b c)) => b
  834. (collect-or #Z()) => nil
  835.  
  836. [Function]
  837. collect items
  838. collect type items
  839.  
  840. collect returns a sequence containing the elements of the series items. The
  841. type is a type specifier indicating the type of sequence to be created. It must
  842. be either a proper subtype of sequence or the symbol bag. If type is omitted,
  843. it defaults to list. (This function exhibits an argument pattern that is
  844. unusual for Common Lisp: an ``optional'' argument preceding a required
  845. argument. This pattern cannot be expressed in the usual manner with &optional.
  846. It is indicated above by two definition lines, showing the two possible
  847. argument patterns.)
  848.  
  849. If the type is bag, a list is created with the elements in whatever order can
  850. be most efficiently obtained. Otherwise, the order of the elements in the
  851. sequence is the same as the order in items. If type specifies a length (that
  852. is, of a vector) this length must be greater than or equal to the length of
  853. items.
  854.  
  855. The nth element of items is placed in the nth slot of the sequence produced.
  856. Any unneeded slots are left in their initial state. Collecting is significantly
  857. more efficient if it can be determined at compile time whether type is a
  858. subtype of list or vector and for vectors what the length of the vector is.
  859.  
  860. (collect #Z(a b c)) => (a b c)
  861. (collect 'bag #Z(a b c)) => (c a b) or (b a c) or ...
  862. (collect '(vector integer 3) #Z(1 2 3)) => #(1 2 3)
  863.  
  864. [Function]
  865. collect-append sequences
  866. collect-append type sequences
  867.  
  868. Given a series of sequences, collect-append returns a new sequence by
  869. concatenating these sequences together in order. The type is a type specifier
  870. indicating the type of sequence created and must be a proper subtype of
  871. sequence. If type is omitted, it defaults to list. (This function exhibits an
  872. argument pattern that is unusual for Common Lisp: an ``optional'' argument
  873. preceding a required argument. This pattern cannot be expressed in the usual
  874. manner with &optional. It is indicated above by two definition lines, showing
  875. the two possible argument patterns.)
  876.  
  877. It must be possible for every element of every sequence in the input series to
  878. be an element of a sequence of type type. The result does not share any
  879. structure with the sequences in the input.
  880.  
  881. (collect-append #Z((a b) nil (c d))) => (a b c d)
  882. (collect-append 'string #Z("a " "big " "cat")) => "a big cat"
  883.  
  884. [Function]
  885. collect-nconc lists
  886.  
  887. collect-nconc nconcs the elements of the series lists together in order and
  888. returns the result. This is the same as collect-append except that the input
  889. must be a series of lists, the output is always a list, the concatenation is
  890. done rapidly by destructively modifying the input elements, and therefore the
  891. output shares all of its structure with the input elements.
  892.  
  893. [Function]
  894. collect-alist keys values
  895. collect-plist keys values
  896. collect-hash keys values &key :test :size :rehash-size :rehash-threshold
  897.  
  898. Given a series of keys and a series of corresponding values, these functions
  899. return an association list, a property list, and a hash table, respectively.
  900. Following the order of the input, each keys  -values   pair is entered into the
  901. output so that it overrides all earlier associations. If one of the input
  902. series is longer than the other, the extra elements are ignored. The keyword
  903. arguments of collect-hash specify attributes of the hash table produced and
  904. have the same meanings as the arguments to make-hash-table.
  905.  
  906. (collect-alist #Z(a b c) #Z(1 2)) => ((b . 2) (a . 1))
  907. (collect-plist #Z(a b c) #Z(1 2)) => (b 2 a 1)
  908. (collect-hash #Z() #Z(1 2) :test #'eq) => an empty hash table
  909.  
  910. [Function]
  911. collect-file file-name items &optional (printer #'print)
  912.  
  913. This creates a file named file-name and writes the elements of the series items
  914. into it using the function printer. Printer must accept two inputs: an object
  915. and an output stream. (For instance, printer can be print, prin1, princ,
  916. pprint, write-char, write-string, or write-line.) If omitted, printer defaults
  917. to print. The value t is returned. The file is correctly closed, even if an
  918. abort occurs.
  919.  
  920. [Function]
  921. collect-fn type init function &rest series-inputs
  922.  
  923. The higher-order function collect-fn supports the general concept of
  924. collecting. It is identical to collecting-fn except that it returns only the
  925. last element of each series computed. If there are no elements in these series,
  926. the values returned by init are passed on directly as the output of collect-fn.
  927.  
  928. (collect-fn 'integer #'(lambda () 0) #'+ #Z(1 2 3)) => 6
  929. (collect-fn 'integer #'(lambda () 0) #'+ #Z()) => 0
  930. (collect-fn 'integer #'(lambda () 1) #'* #Z(1 2 3 4 5)) => 120
  931.  
  932. [change_end]
  933.  
  934. -------------------------------------------------------------------------------
  935.  
  936. A.2.6. Alteration of Series
  937.  
  938. [change_begin]
  939. Series that come from scanning data structures such as lists and vectors are
  940. closely linked to these structures. The function alter can be used to modify
  941. the underlying data structure with reference to the series derived from it.
  942. (Conversely, it is possible to modify a series by destructively modifying the
  943. data structure it is derived from. However, given the lazy evaluation nature of
  944. series, the effects of such modifications can be very hard to predict. As a
  945. result, this kind of modification is inadvisable.)
  946.  
  947. [Function]
  948. alter destinations items
  949.  
  950. alter changes the series destinations so that it contains the elements in the
  951. series items. More importantly, in the manner of setf, the data structure that
  952. underlies destinations is changed so that if the series destinations were to be
  953. regenerated, the new values would be obtained. The alteration process stops as
  954. soon as either input runs out of elements. The value nil is always returned. In
  955. the example below each negative element in a list is replaced with its square.
  956.  
  957. (let* ((data (list 1 -2 3 4 -5 6))
  958.        (x (choose-if #'minusp (scan data))))
  959.   (alter x (#M* x x))
  960.   data)
  961.   => (1 4 3 4 25 6)
  962.  
  963. alter can be applied only to series that are alterable. scan, scan-alist,
  964. scan-multiple, scan-plist, and scan-lists-of-lists-fringe produce alterable
  965. series. However, the alterability of the output of scan-lists-of-lists-fringe
  966. is incomplete. If scan-lists-of-lists-fringe is applied to an object that is a
  967. leaf, altering the output series does not change the object.
  968.  
  969. In general, the output of a transducer is alterable as long as the elements of
  970. the output come directly from the elements of an input that is alterable. In
  971. particular, the outputs of choose, choose-if, split, split-if, cotruncate,
  972. until, until-if, and subseries are alterable as long as the corresponding
  973. inputs are alterable.
  974.  
  975. [Function]
  976. to-alter items alter-fn &rest args
  977.  
  978. Given a series items, to-alter returns an alterable series A containing the
  979. same elements. The argument alter-fn is a function. The remaining arguments are
  980. all series. Let these series be S1, ..., Sn. If there are n arguments after
  981. alter-fn, alter-fn must accept n+1 inputs. If (alter A B) is later encountered,
  982. the expression (map-fn t alter-fn B S1 ... Sn) is implicitly evaluated. For
  983. each element in B, alter-fn should make appropriate changes in the data
  984. structure underlying A.
  985.  
  986. As an example, consider the following definition of a series function that
  987. scans the elements of a list. Alteration is performed by changing cons cells in
  988. the list being scanned.
  989.  
  990. (defun scan-list (list)
  991.   (declare (optimizable-series-function))
  992.   (let ((sublists (scan-sublists list)))
  993.     (to-alter (#Mcar sublists)
  994.               #'(lambda (new parent) (setf (car parent) new))
  995.               sublists)))
  996.  
  997. [change_end]
  998.  
  999. -------------------------------------------------------------------------------
  1000.  
  1001. A.3. Optimization
  1002.  
  1003. [change_begin]
  1004. Series expressions are transformed into loops by pipelining them-the
  1005. computation is converted from a form where entire series are computed one after
  1006. the other to a form where the series are incrementally computed in parallel. In
  1007. the resulting loop, each individual element is computed just once, used, and
  1008. then discarded before the next element is computed. For this pipelining to be
  1009. possible, a number of restrictions have to be satisfied. Before these
  1010. restrictions are explained, it will be useful to consider a related issue.
  1011.  
  1012. The composition of two series functions cannot be pipelined unless the
  1013. destination function consumes series elements in the same order that the source
  1014. function produces them. Taken together, the series functions guarantee that
  1015. this will always be true, because they all follow the same fixed processing
  1016. order. In particular, they are all preorder functions-they process the elements
  1017. of their series inputs and outputs in ascending order starting with the first
  1018. element. Further, while it is easy for users to define new series functions, it
  1019. is impossible to define one that is not a preorder function.
  1020.  
  1021. It turns out that most series operations can easily be implemented in a
  1022. preorder fashion, the most notable exceptions being reversal and sorting. As a
  1023. result, little is lost by outlawing non-preorder series functions. If some
  1024. non-preorder operation has to be applied to a series, the series can be
  1025. collected into a list or vector and the operation applied to this new data
  1026. structure. (This is inefficient, but no less efficient than what would be
  1027. required if non-preorder series functions were supported.)
  1028. [change_end]
  1029.  
  1030. -------------------------------------------------------------------------------
  1031.  
  1032.    *  Basic Restrictions
  1033.    *  Constraint Cycles
  1034.    *  Defining New Series Functions
  1035.    *  Declarations
  1036.  
  1037. -------------------------------------------------------------------------------
  1038.  
  1039. A.3.1. Basic Restrictions
  1040.  
  1041. [change_begin]
  1042. The transformation of series expressions into loops is required to occur at
  1043. some time before compiled code is actually run. Optimization may or may not be
  1044. applied to interpreted code. If any of the restrictions described below are
  1045. violated, optimization is not possible. In this situation, a warning message is
  1046. issued at the time optimization is attempted and the code is left unoptimized.
  1047. This is not a fatal error and does not prevent the correct results from being
  1048. computed. However, given the large improvements in efficiency to be gained, it
  1049. is well worth fixing any violations that occur. This is usually easy to do.
  1050.  
  1051. [Variable]
  1052. *suppress-series-warnings*
  1053.  
  1054. If this variable is set (or bound) to anything other than its default value of
  1055. nil, warnings about conditions that block the optimization of series
  1056. expressions are suppressed.
  1057.  
  1058. Before the restrictions on series expressions are discussed, it will be useful
  1059. to define precisely what is meant by the term series expression. This term is
  1060. semantic rather than syntactic in nature. Imagine a program converted from Lisp
  1061. code into a data flow graph. In a data flow graph, functions are represented as
  1062. boxes, and both control flow and data flow are represented as arrows between
  1063. the boxes. Constructs such as let and setq are converted into patterns of data
  1064. flow arcs. Control constructs such as if and loop are converted into patterns
  1065. of control flow arcs. Suppose further that all loops have been converted into
  1066. tail recursions so that the graph is acyclic.
  1067.  
  1068. A series expression is a subgraph of the data flow graph for a program that
  1069. contains a group of interacting series functions. More specifically, given a
  1070. call f on a series function, the series expression E containing it is defined
  1071. as follows. E contains f. Every function using a series created by a function
  1072. in E is in E. Every function computing a series used by a function in E is in
  1073. E. Finally, suppose that two functions g and h are in E and that there is a
  1074. data flow path consisting of series and/or non-series data flow arcs from g to
  1075. h. Every function touched by this path (be it a series function or not) is in
  1076. E.
  1077.  
  1078. For optimization to be possible, series expressions have to be statically
  1079. analyzable. As with most other optimization processes, a series expression
  1080. cannot be transformed into a loop at compile time, unless it can be determined
  1081. at compile time exactly what computation is being performed. This places a
  1082. number of relatively minor limits on what can be written. For example, for
  1083. optimization to be possible the type arguments to higher-order functions such
  1084. as map-fn and collecting-fn have to be quoted constants. Similarly, the numeric
  1085. arguments to chunk have to be constants. In addition, if funcall is used to
  1086. call a series function, the function called has to be of the form (function
  1087. ...).
  1088.  
  1089. For optimization to be possible, every series created within a series
  1090. expression must be used solely inside the expression. If a series is
  1091. transmitted outside of the expression that creates it, it has to be physically
  1092. represented as a whole. This is incompatible with the transformations required
  1093. to pipeline the creating expression. To avoid this problem, a series must not
  1094. be returned as a result of a series expression as a whole, assigned to a free
  1095. variable, assigned to a special variable, or stored in a data structure. A
  1096. corollary of the last point is that when defining new optimizable series
  1097. functions, series cannot be passed into &rest arguments. Further, optimization
  1098. is blocked if a series is passed as an argument to an ordinary Lisp function.
  1099. Series can be passed only to the series functions in section A.2 and to new
  1100. series functions defined using the declaration optimizable-series-function.
  1101.  
  1102. For optimization to be possible, series expressions must correspond to
  1103. straight-line computations. That is to say, the data flow graph corresponding
  1104. to a series expression cannot contain any conditional branches. (Complex
  1105. control flow is incompatible with pipelining.) Optimization is possible in the
  1106. presence of standard straight-line forms such as progn, funcall, setq, lambda,
  1107. let, let*, and multiple-value-bind as long as none of the variables bound are
  1108. special. There is also no problem with macros as long as they expand into
  1109. series functions and straight-line forms. However, optimization is blocked by
  1110. forms that specify complex control flow (i.e., conditionals if, cond, etc.,
  1111. looping constructs loop, do, etc., or branching constructs tagbody, go, catch,
  1112. etc.).
  1113.  
  1114. In the first example below, optimization is blocked, because the if form is
  1115. inside the series expression. In the second example, however, optimization is
  1116. possible, because although the if feeds data to the series expression, it is
  1117. not inside the corresponding subgraph. Both of the expressions below produce
  1118. the same value, but the second one is much more efficient.
  1119.  
  1120. (collect (if flag (scan x) (scan y)))  ;Warning message issued
  1121. (collect (scan (if flag x y)))
  1122.  
  1123. [change_end]
  1124.  
  1125. -------------------------------------------------------------------------------
  1126.  
  1127. A.3.2. Constraint Cycles
  1128.  
  1129. [change_begin]
  1130. Even if a series expression satisfies all of the restrictions above, it still
  1131. may not be possible to transform the expression into a loop. The sole remaining
  1132. problem is that if a series is used in two places, the two uses may place
  1133. incompatible constraints on the times at which series elements should be
  1134. produced.
  1135.  
  1136. The series expression below shows a situation where this problem arises. The
  1137. expression creates a series x of the elements in a list. It then creates a
  1138. normalized series by dividing each element of x by the sum of the elements in
  1139. x. Finally, the expression returns the maximum of the normalized elements.
  1140.  
  1141. (let ((x (scan '(1 2 5 2))))           ;Warning message issued
  1142.   (collect-max (#M/ x (series (collect-sum x))))) => 1/2
  1143.  
  1144. The two uses of x in the expression place contradictory constraints on the way
  1145. pipelined evaluation must proceed; collect-sum requires that all of the
  1146. elements of x be produced before the sum can be returned, and series requires
  1147. that its input be available before it can start to produce its output. However,
  1148. #M/ requires that the first element of x be available at the same time as the
  1149. first element of the output of series. For pipelining to work, the first
  1150. element of the output of series (and therefore the output of collect-sum) must
  1151. be available before the second element of x is produced. Unfortunately, this is
  1152. impossible.
  1153.  
  1154. The essence of the inconsistency above is the cycle of constraints used in the
  1155. argument. This in turn stems from a cycle in the data flow graph underlying the
  1156. expression. In figure A-1 function calls are represented by boxes and data flow
  1157. is represented by arrows. Simple arrows indicate the flow of series values and
  1158. cross-hatched arrows indicate the flow of non-series values.
  1159.  
  1160.  
  1161.  
  1162. ----------------------------------------------------------------
  1163. Figure A-1: A Constraint Cycle in a Series Expression
  1164.  
  1165.    +------+                                    +-----+   +-----+
  1166. -->| scan |----------------------------------->| #M/ |-->| max |-->
  1167.    +------+  \   +-----+       +--------+  /   +-----+   +-----+
  1168.               -->| sum |-++++->| series |--
  1169.                  +-----+       +--------+
  1170.  
  1171. ----------------------------------------------------------------
  1172.  
  1173. Given a data flow graph corresponding to a series expression, a constraint
  1174. cycle is a closed oriented loop of data flow arcs such that each arc is
  1175. traversed exactly once and no non-series arc is traversed backward. (Series
  1176. data flow arcs can be traversed in either direction.) A constraint cycle is
  1177. said to pass through an input or output port when exactly one of the arcs in
  1178. the cycle touches the port. In figure A-1 the data flow arcs touching scan,
  1179. sum, series, and #M/ form a constraint cycle. Note that if the output of scan
  1180. were not a series, this loop would not be a constraint cycle, because there
  1181. would be no valid way to traverse it. Also note that while the constraint cycle
  1182. passes through all the other ports it touches, it does not pass through the
  1183. output of scan.
  1184.  
  1185. Whenever a constraint cycle passes through a non-series output, an argument
  1186. analogous to the one above can be constructed and therefore pipelining will be
  1187. impossible. When this situation arises, a warning message is issued identifying
  1188. the problematical port and the cycle passing through it. For instance, the
  1189. warning triggered by the example above states that the constraint cycle
  1190. associated with scan, collect-sum, series, and #M/ passes through the
  1191. non-series output of collect-sum.
  1192.  
  1193. Given this kind of detailed information, it is easy to alleviate the problem.
  1194. To start with, every cycle must contain at least one function that has two
  1195. series data flows leaving it. At worst, the cycle can be broken by duplicating
  1196. this function (and any functions computing series used by it). For instance,
  1197. the example above can be rewritten as shown below.
  1198.  
  1199. (let ((x (scan '(1 2 5 2)))
  1200.       (sum (collect-sum (scan '(1 2 5 2)))))
  1201.   (collect-max (#M/ x (series sum))))
  1202.   => 1/2
  1203.  
  1204. It would be easy enough to automatically apply code copying to break
  1205. problematical constraint cycles. However, this is not done for two reasons.
  1206. First, there is considerable virtue in maintaining the property that each
  1207. function in a series expression turns into one piece of computation in the loop
  1208. produced. Users can be confident that series expressions that look simple and
  1209. efficient actually are simple and efficient. Second, with a little creativity,
  1210. constraint problems can often be resolved in ways that are much more efficient
  1211. than copying code. In the example above, the conflict can be eliminated
  1212. efficiently by interchanging the operation of computing the maximum with the
  1213. operation of normalizing an element.
  1214.  
  1215. (let ((x (scan '(1 2 5 2))))
  1216.   (/ (collect-max x) (collect-sum x))) => 1/2
  1217.  
  1218. The restriction that optimizable series expressions cannot contain constraint
  1219. cycles that pass through non-series outputs places limitations on the
  1220. qualitative character of optimizable series expressions. In particular, they
  1221. all must have the general form of creating some number of series using
  1222. scanners, computing various intermediate series using transducers, and then
  1223. computing one or more summary results using collectors. The output of a
  1224. collector cannot be used in the intermediate computation unless it is the
  1225. output of a separate subexpression.
  1226.  
  1227. It is worthy of note that the last expression above fixes the constraint
  1228. conflict by moving the non-series output out of the cycle, rather than by
  1229. breaking the cycle. This illustrates the fact that constraint cycles that do
  1230. not pass through non-series outputs do not necessarily cause problems. They
  1231. cause problems only if they pass through off-line ports.
  1232.  
  1233. A series input port or series output port of a series function is on-line if
  1234. and only if it is processed in lockstep with all the other on-line ports as
  1235. follows: the initial element of each on-line input is read, then the initial
  1236. element of each on-line output is written, then the second element of each
  1237. on-line input is read, then the second element of each on-line output is
  1238. written, and so on. Ports that are not on-line are off-line. If all of the
  1239. series ports of a function are on-line, the function is said to be on-line;
  1240. otherwise, it is off-line. (The above extends the standard definition of the
  1241. term on-line so that it applies to individual ports as well as whole
  1242. functions.)
  1243.  
  1244. If all of the ports a cycle passes through are on-line, the lockstep processing
  1245. of these ports guarantees that there cannot be any conflicts between the
  1246. constraints associated with the cycle. However, passing through an off-line
  1247. port leads to the same kinds of problems as passing through a non-series
  1248. output.
  1249.  
  1250. Most of the series functions are on-line. In particular, scanners and
  1251. collectors are all on-line as are many transducers. However, the transducers in
  1252. section A.2.4 are off-line. In particular, the series inputs of catenate,
  1253. choose-if, chunk, expand, mask, mingle, positions, and subseries along with the
  1254. series outputs of choose, split, and split-if are off-line.
  1255.  
  1256. In summary, the fourth and final restriction is that for optimization to be
  1257. possible, a series expression cannot contain a constraint cycle that passes
  1258. through a non-series output or an off-line port. Whenever this restriction is
  1259. violated a warning message is issued. Violations can be fixed either by
  1260. breaking the cycle or restructuring the computation so that the offending port
  1261. is removed from the cycle.
  1262. [change_end]
  1263.  
  1264. -------------------------------------------------------------------------------
  1265.  
  1266. A.3.3. Defining New Series Functions
  1267.  
  1268. [change_begin]
  1269. New functions operating on series can be defined just as easily as new
  1270. functions operating on any other data type. However, expressions containing
  1271. these new functions cannot be transformed into loops unless a complete analysis
  1272. of the functions is available. Among other things, this implies that the
  1273. definition of a new series function must appear before its first use.
  1274.  
  1275. [Declaration specifier]
  1276. optimizable-series-function
  1277.  
  1278. The declaration specifier (optimizable-series-function integer) indicates that
  1279. the function being defined is a series function that needs to be analyzed so
  1280. that it can be optimized when it appears in series expressions. (A warning is
  1281. issued if the function being defined neither takes a series as input nor
  1282. produces a series as output.) Integer (default 1) specifies the number of
  1283. values returned by the function being defined. (This cannot necessarily be
  1284. determined by local analysis.) The only place optimizable-series-function is
  1285. allowed to appear is in a declaration immediately inside a defun. As an
  1286. example, the following shows how a simplified version of collect-sum could be
  1287. defined.
  1288.  
  1289. (defun simple-collect-sum (numbers)
  1290.   (declare (optimizable-series-function 1))
  1291.   (collect-fn 'number #'(lambda () 0) #'+ numbers))
  1292.  
  1293. [Declaration specifier]
  1294. off-line-port
  1295.  
  1296. The declaration specifier (off-line-port port-spec1 port-spec2 ...) specifies
  1297. that the indicated inputs and outputs are off-line. This declaration specifier
  1298. is only allowed in a defun that contains the declaration
  1299. optimizable-series-function. Each port-spec must either be a symbol that is one
  1300. of the inputs of the function or an integer j indicating the jth output
  1301. (counting from zero). For example, (off-line-port x 1) indicates that the input
  1302. x and the secona large
  1303. number of useful operations that can be performed on series. However, this
  1304. functionality can be boiled down to a small number of primitive constructs.
  1305.  
  1306. collecting-fn embodies the fundamental idea of series computations that utilize
  1307. internal state. It can be used as the basis for defining any on-line
  1308. transducer.
  1309.  
  1310. until embodies the fundamental idea of producing a series that is shorter than
  1311. the shortest input series. In particular, it embodies the idea of computing a
  1312. bounded series from non-series inputs. Together with collecting-fn, until can
  1313. be used to define scan-fn, which can be used as the basis for defining all the
  1314. other scanners.
  1315.  
  1316. collect-last embodies the fundamental idea of producing a non-series value from
  1317. a series. Together with collecting-fn, it can be used to define collect-fn,
  1318. which (with the occasional assistance of until) can be used as the basis for
  1319. defining all the other collectors.
  1320.  
  1321. producing embodies the fundamental idea of preorder computation. It can be used
  1322. as the basis for defining all the other series functions, including the
  1323. off-line transducers.
  1324.  
  1325. In addition to the above, four primitives support various specialized aspects
  1326. of series functions. Alterability is supported by the function to-alter and the
  1327. declaration propagate-alterability. The propagation of type information is
  1328. supported by the type specifier series-element-type. The best implementation of
  1329. certain series functions requires the form encapsulated.
  1330.  
  1331. [Macro]
  1332. producing output-list input-list {declaration}* {form}*
  1333.  
  1334. producing computes and returns a group of series and non-series outputs given a
  1335. group of series and non-series inputs. The key feature of producing is that
  1336. some or all of the series inputs and outputs can be processed in an off-line
  1337. way. To support this, the processing in the body (consisting of the forms) is
  1338. performed from the perspective of generators and gatherers (see appendix B).
  1339. Each series input is converted to a generator before being used in the body.
  1340. Each series output is associated with a gatherer in the body.
  1341.  
  1342. The output-list has the same syntax as the binding list of a let. The names of
  1343. the variables must be distinct from each other and from the names of the
  1344. variables in the input-list. If there are n variables in the output-list,
  1345. producing computes n outputs. There must be at least one output variable. The
  1346. variables act as the names for the outputs and can be used in either of two
  1347. ways. First, if an output variable has a value associated with it in the
  1348. output-list, then the variable is treated as holding a non-series value. The
  1349. variable is initialized to the indicated value and can be used in any way
  1350. desired in the body. The eventual output value is whatever value is in the
  1351. variable when the execution of the body terminates. Second, if an output
  1352. variable does not have a value associated with it in the output-list, the
  1353. variable is given as its value a gatherer that collects elements. The only
  1354. valid way to use the variable in the body is in a call on next-out. The output
  1355. returned is a series containing these elements. If the body never terminates,
  1356. this series is unbounded.
  1357.  
  1358. The input-list also has the same syntax as the binding list of a let. The names
  1359. of the variables must be distinct from each other and the names of the
  1360. variables in the output-list. The values can be series or non-series. If the
  1361. value is not explicitly specified, it defaults to nil. The variables act
  1362. logically both as inputs and state variables and can be used in one of two
  1363. ways. First, if an input variable is associated with a non-series value, then
  1364. it is given this value before the evaluation of the body begins and can be used
  1365. in any way desired in the body. Second, if an input variable is associated with
  1366. a series, then the variable is given a generator corresponding to this series
  1367. as its initial value. The only valid way to use the variable in the body is in
  1368. a call on next-in.
  1369.  
  1370. There can be declarations at the start of the body. However, the only
  1371. declarations allowed are ignore declarations, type declarations, and
  1372. propagate-alterability declarations (see below). In particular, it is an error
  1373. for any of the input or output variables to be special.
  1374.  
  1375. In conception, the body can contain arbitrary Lisp expressions. After the
  1376. appropriate generators and gatherers have been set up, the body is executed
  1377. until it terminates. If the body never terminates, the series outputs (if any)
  1378. are unbounded in length and the non-series outputs (if any) are never produced.
  1379.  
  1380. Although easy to understand, this view of what can happen in the body presents
  1381. severe difficulties when optimizing (and even when evaluating) series
  1382. expressions that contain calls on producing. As a result, several limitations
  1383. are imposed on the form of the body to simplify the processing required.
  1384.  
  1385. The first limitation is that, exclusive of any declarations, the body must have
  1386. the form (loop (tagbody ...)). The following example shows how producing could
  1387. be used to implement a scanner creating an unbounded series of integers.
  1388.  
  1389. (producing (nums) ((num 0))
  1390.   (declare (integer num) (type (series integer) nums))
  1391.   (loop
  1392.     (tagbody
  1393.       (setq num (1+ num))
  1394.       (next-out nums num))))
  1395.   => #Z(1 2 3 4 ...)
  1396.  
  1397. The second limitation is that the form terminate-producing must be used to
  1398. terminate the execution of the body. Any other method of terminating the body
  1399. (with return, for example) is an error. The following example shows how
  1400. producing could be used to implement the operation of summing a series. The
  1401. function terminate-producing is used to stop the computation when numbers runs
  1402. out of elements.
  1403.  
  1404. (producing ((sum 0)) ((numbers #Z(1 2 3)) num)
  1405.   (loop
  1406.     (tagbody
  1407.       (setq num (next-in numbers (terminate-producing)))
  1408.       (setq sum (+ sum num)))))
  1409.   => 6
  1410.  
  1411. The third limitation is that calls on next-out associated with output variables
  1412. must appear at top level in the tagbody in the body. They cannot be nested in
  1413. other forms. In addition, an output variable can be the destination of at most
  1414. one call on next-out and if it is the destination of a next-out, it cannot be
  1415. used in any other way.
  1416.  
  1417. If the call on next-out for a given output appears in the final part of the
  1418. tagbody in the body, after everything other than other calls on next-out, then
  1419. the output is an on-line output-a new value is written on every cycle of the
  1420. body. Otherwise the output is off-line.
  1421.  
  1422. The following example shows how producing could be used to split a series into
  1423. two parts. Items are read in one at a time and tested. Depending on the test,
  1424. they are written to one of two outputs. Note the use of labels and branches to
  1425. keep the calls on next-out at top level. Both outputs are off-line. The first
  1426. example above shows an on-line output.
  1427.  
  1428. (producing (items-1 items-2) ((items #Z(1 -2 3 -4)) item)
  1429.   (loop
  1430.     (tagbody (setq item (next-in items (terminate-producing)))
  1431.              (if (not (plusp item)) (go D))
  1432.              (next-out items-1 item)
  1433.              (go F)
  1434.       D      (next-out items-2 item)
  1435.       F      )))
  1436.   => #Z(1 3) and #Z(-2 -4)
  1437.  
  1438. The fourth limitation is that the calls on next-in associated with an input
  1439. variable v must appear at top level in the tagbody in the body, nested in
  1440. assignments of the form (setq var (next-in v ...)). They cannot be nested in
  1441. other forms. In addition, an input variable can be the source for at most one
  1442. call on next-in and if it is the source for a next-in, it cannot be used in any
  1443. other way.
  1444.  
  1445. If the call on next-in for a given input has as its sole termination action
  1446. (terminate-producing) and appears in the initial part of the tagbody in the
  1447. body, before anything other than similar calls on next-in, then the input is an
  1448. on-line input-a new value is read on every cycle of the body. Otherwise the
  1449. input is off-line.
  1450.  
  1451. The example below shows how producing could be used to concatenate two series.
  1452. To start with, elements are read from the first input series. When this runs
  1453. out, a flag is set and reading begins from the second input. Both inputs are
  1454. off-line. (Compare this to the example above, which shows an on-line input.)
  1455.  
  1456. (producing (items) ((item-1 #Z(1 2))
  1457.                     (item-2 #Z(3 4))
  1458.                     (in-2 nil)
  1459.                     item)
  1460.   (loop
  1461.     (tagbody (if in-2 (go D))
  1462.              (setq item (next-in item-1 (setq in-2 t) (go D)))
  1463.              (go F)
  1464.       D      (setq item (next-in item-2 (terminate-producing)))
  1465.       F      (next-out items item))))
  1466.   => #Z(1 2 3 4)
  1467.  
  1468. [Macro]
  1469. terminate-producing
  1470.  
  1471. This form (which takes no arguments) is used to terminate execution of (the
  1472. expansion of) the producing macro.
  1473.  
  1474. As with the form go, terminate-producing does not return any values; rather,
  1475. control immediately leaves the current context.
  1476.  
  1477. The form terminate-producing is allowed to appear only in a producing body and
  1478. causes the termination of the enclosing call on producing.
  1479.  
  1480. [Declaration specifier]
  1481. propagate-alterability
  1482.  
  1483. The declaration specifier (propagate-alterability input output) indicates that
  1484. attempts to alter an element of output should be satisfied by altering the
  1485. corresponding element of input. (The corresponding element of input is the one
  1486. most recently read at the moment when the output element is written.)
  1487.  
  1488. This declaration may appear only in a call on producing. The input and output
  1489. arguments must be an input and an output, respectively, of the producing macro.
  1490. The example below shows how the propagation of alterability could be supported
  1491. in a simplified version of until.
  1492.  
  1493. (defun simple-until (bools items)
  1494.   (declare (optimizable-series-function))
  1495.   (producing (z) ((x bools) (y items) bool item)
  1496.     (declare (propagate-alterability y z))
  1497.     (loop
  1498.       (tagbody
  1499.         (setq bool (next-in x (terminate-producing)))
  1500.         (setq item (next-in y (terminate-producing)))
  1501.         (if bool (terminate-producing))
  1502.         (next-out z item)))))
  1503.  
  1504. [Macro]
  1505. encapsulated encapsulating-fn scanner-or-collector
  1506.  
  1507. Some of the features provided by Common Lisp are supported solely by
  1508. encapsulating forms. For example, there is no way to specify a cleanup
  1509. expression that will always be run, even when an abort occurs, without using
  1510. unwind-protect. encapsulated makes it possible to take advantage of forms such
  1511. as unwind-protect when defining a series function.
  1512.  
  1513. encapsulated specifies a function that places an encapsulating form around the
  1514. computation performed by its second argument. The first argument must be a
  1515. quoted function that takes a Lisp expression and wraps the appropriate
  1516. encapsulating form around it, returning the resulting code. The second input
  1517. must be a literal call on scan-fn, scan-fn-inclusive, or collect-fn. The second
  1518. argument can count on being evaluated in the scope of the encapsulating form.
  1519. The values returned by the second argument are returned as the values of
  1520. encapsulated. The following shows how encapsulated could be used to define a
  1521. simplified version of collect-file.
  1522.  
  1523. (defun collect-file-wrap (file name body)
  1524.   `(with-open-file (,file ,name :direction :output) ,body))
  1525. (defmacro simple-collect-file (name items)
  1526.   (let ((file (gensym)))
  1527.     `(encapsulated #'(lambda (body)
  1528.                        (collect-file-wrap ',file ',name body))
  1529.                    (collect-fn t #'(lambda () t)
  1530.                                #'(lambda (state item)
  1531.                                    (print item ,file)
  1532.                                    state)
  1533.                                ,items))))
  1534.  
  1535. [change_end]
  1536.  
  1537. -------------------------------------------------------------------------------
  1538.  
  1539.